package com.springboot.others.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.springboot.others.entity.Address;
import com.springboot.others.entity.Customer;
import com.springboot.others.entity.dto.PageCustomerDTO;
import com.springboot.others.entity.vo.ResultPage;
import com.springboot.others.exception.BaseException;
import com.springboot.others.mapper.AddressMapper;
import com.springboot.others.mapper.CustomerMapper;
import com.springboot.others.service.CustomerService;
import org.apache.ibatis.annotations.Options;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
@Transactional
@CacheConfig(cacheNames = "customer")
public class CustomerServiceImpl implements CustomerService {

    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private AddressMapper addressMapper;

    @Override
    @Cacheable(cacheNames = "customer", key = "#id")
    public Customer findById(Integer id) {
        Customer customer = customerMapper.selectById(id);
        Address address = addressMapper.getAddressById(customer.getAddressId());
        customer.setAddress(address);
        return customer;
    }

    @Override
    public List<Customer> findAll() {
        //单表查询再填充效率太低
        //使用resultMap：1.分成两个子查询配合resultMap：数据量高，有n+1问题; 2.使用一个连接查询配合resultMap
        return customerMapper.selectAll();
    }

    @Override
    @Options(useGeneratedKeys = true, keyProperty = "customer_id")
    @CacheEvict(allEntries = true)
    @Transactional
    public void save(Customer customer) {
        customer.setLastUpdate(LocalDateTime.now());
        customer.setCreateDate(LocalDateTime.now());
        if (customer.getAddressId() == null){
            addressMapper.insert(customer.getAddress());
            customer.setAddressId(customer.getAddress().getAddressId());
        }
        customerMapper.add(customer);
    }

    @Override
    @CacheEvict(allEntries = true)
    public void deleteById(Integer id) {
        customerMapper.del(id);
    }

    @Override
    @CacheEvict(allEntries = true)
    @Transactional
    public void update(Customer customer) {
        customer.setLastName(LocalDateTime.now().toString());
        if (customer.getAddress() == null){
            //不需修改地址
            customerMapper.update(customer);
            return;
        }

        //需要修改地址
        //1.查询地址id
        Integer addressId;

        if(customer.getAddressId() != null){
            addressId = customer.getAddressId();
        }else if (customer.getAddress().getAddressId() != null){
            addressId = customer.getAddress().getAddressId();
        }else{
            addressId = customerMapper.getAddressIdByCustomerId(customer.getCustomerId());
        }
        customer.setAddressId(addressId);
        customer.getAddress().setAddressId(addressId);

        //2.判断当前地址是否存在
        if(addressMapper.getAddressById(addressId) == null){
            throw new BaseException("地址不存在");
        }

        //3.判断当前用户的地址是否有其他客户使用
        if(customerMapper.countAddressByAddressId(addressId) > 1) {
            //有，不修改原来的地址，新增地址
            Address newAddress = customer.getAddress();
            //只修改不为null的字段
            Address oldAddress = addressMapper.getAddressById(addressId);

            newAddress.setAddress(newAddress.getAddress() != null ?
                    newAddress.getAddress() : oldAddress.getAddress());
            newAddress.setAddress2(newAddress.getAddress2() != null ?
                    newAddress.getAddress2() : oldAddress.getAddress2());
            newAddress.setDistrict(newAddress.getDistrict() != null ?
                    newAddress.getDistrict() : oldAddress.getDistrict());
            newAddress.setCityId(newAddress.getCityId() != null ?
                    newAddress.getCityId() : oldAddress.getCityId());
            newAddress.setPostalCode(newAddress.getPostalCode() != null ?
                    newAddress.getPostalCode() : oldAddress.getPostalCode());
            newAddress.setPhone(newAddress.getPhone() != null ?
                    newAddress.getPhone() : oldAddress.getPhone());
            newAddress.setLocation(newAddress.getLocation() != null ?
                    newAddress.getLocation() : oldAddress.getLocation());
            newAddress.setLastUpdate(LocalDateTime.now());

            addressMapper.insert(newAddress);
            //更新用户的地址id
            customer.setAddressId(newAddress.getAddressId());
        }else {
            //没有，则直接修改当前地址
            addressMapper.update(customer.getAddress());
        }

        customerMapper.update(customer);
    }

    /**
     * 根据条件分页查询
     * @param pageCustomerDTO
     * @return
     */
    @Override
    public ResultPage getPageByCondition(PageCustomerDTO pageCustomerDTO) {
// 如果 pageCustomerDTO 为 null，则初始化一个新的 PageCustomerDTO 对象
        if (pageCustomerDTO == null) {
            pageCustomerDTO = new PageCustomerDTO();
        }

        // 检查 pageNO 是否为 null，并设置默认值
        Integer pageNO = pageCustomerDTO.getPageNo();
        if (pageNO == null) {
            pageNO = 1;
            pageCustomerDTO.setPageNo(pageNO);
        }

        // 检查 pageSize 是否为 null，并设置默认值
        Integer pageSize = pageCustomerDTO.getPageSize();
        if (pageSize == null) {
            pageSize = 5;
            pageCustomerDTO.setPageSize(pageSize);
        }

        Page<Customer> page = PageHelper.startPage(pageCustomerDTO.getPageNo(), pageCustomerDTO.getPageSize());
        List<Customer> customerList = customerMapper.listByCondition(pageCustomerDTO);

        if (customerList != null && customerList.size() > 0){
            return new ResultPage(page.getTotal(),page.getResult(),
                    page.toPageInfo().isIsFirstPage(),
                    page.toPageInfo().isIsLastPage());
        }else {
            return null;
        }
    }
}
